package deepr.lib;

import deepr.anno.LifeCycle;
import deepr.exception.LifeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.Assert;

import java.lang.reflect.Array;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
public class CastLib {

    public static DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
    public static DateFormat fdt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static <K, V> Map<K, V> castMap(Object obj, Class<K> tClass, Class<V> vClass) throws LifeException {
        HashMap<K, V> result = new HashMap<>();
        if (obj instanceof Map<?, ?>) {
            Map<?, ?> map = (Map<?, ?>) (obj);
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                result.put(tClass.cast(entry.getKey()), vClass.cast(entry.getValue()));
            }
            return result;
        }
        throw new LifeException("CastList Error", LifeCycle.CAST, obj);
    }

    public static <T> String[] castArrayString(Object obj) throws LifeException {
        if (obj.getClass().isArray()) {
            int length = Array.getLength(obj);
            String[] os = new String[length];
            for (int i = 0; i < os.length; i++) {
                os[i] = (String) Array.get(obj, i);
            }
            return os;
        }
        throw new LifeException("CastList Error", LifeCycle.CAST, obj);
    }

    public static <T> List<T> castList(Object obj, Class<T> clazz) throws LifeException {
        List<T> result = new ArrayList<T>();
        int count = 0;
        if (obj instanceof List<?>) {
            for (Object o : (List<?>) obj) {
                result.add(clazz.cast(o));
                count++;
                if (count > 5) {
                    throw new LifeException("List Too Long", LifeCycle.CAST, obj);
                }
            }
            return result;
        }
        throw new LifeException("CastList Error", LifeCycle.CAST, obj);
    }

    public static Object toInteger(String key, Object value) {
        if (value instanceof String) {
            return Integer.parseInt((String) value);
        }
        if (value instanceof Integer) {
            return value;
        }
        if (value instanceof Float || value instanceof Long) {
            return (Integer) value;
        }
        if (value.getClass().isArray()) {
            Object[] a = (Object[]) value;
            for (int i = 0; i < a.length; i++) {
                a[i] = toInteger(key, a[i]);
            }
            return a;
        }
        Assert.isTrue(false, key + " value can't to int");
        return null;
    }

    public static Object toDate(String key, Object value) throws ParseException {
        if (value instanceof String) {
            return fmt.parse((String) value);
        }
        if (value instanceof Date) {
            return value;
        }
        if (value.getClass().isArray()) {
            Object[] a = (Object[]) value;
            for (int i = 0; i < a.length; i++) {
                a[i] = toDate(key, a[i]);
            }
            return a;
        }
        Assert.isTrue(false, key + " value can't to date");
        return null;
    }

    public static Object toDateTime(String key, Object value) throws ParseException {
        if (value instanceof String) {
            return fdt.parse((String) value);
        }
        if (value instanceof LocalDateTime) {
            return value;
        }
        if (value.getClass().isArray()) {
            Object[] a = (Object[]) value;
            for (int i = 0; i < a.length; i++) {
                a[i] = toDateTime(key, a[i]);
            }
            return a;
        }
        Assert.isTrue(false, key + " value can't to datetime");
        return null;
    }

}
